pacenotes_installer\wizard\scene/
progress_page.rs1use windows_sys::Win32::Foundation::{HWND, LPARAM, WPARAM};
5use windows_sys::Win32::UI::Controls as ctl;
6use windows_sys::Win32::UI::WindowsAndMessaging as wm;
7
8pub const PROGRESS_SCALE: u32 = 1000;
10
11pub unsafe fn init_progress(dialog: HWND) {
12 wm::SendDlgItemMessageW(
13 dialog,
14 crate::wizard::control_ids::IDC_S6_PROGRESS as i32,
15 ctl::PBM_SETRANGE32,
16 0,
17 PROGRESS_SCALE as LPARAM,
18 );
19}
20
21pub unsafe fn set_progress(dialog: HWND, position: u32) {
22 wm::SendDlgItemMessageW(
23 dialog,
24 crate::wizard::control_ids::IDC_S6_PROGRESS as i32,
25 ctl::PBM_SETPOS,
26 position as WPARAM,
27 0,
28 );
29}
30
31pub unsafe fn show_progress(
32 dialog: HWND,
33 state: &mut crate::wizard::state::WizardState,
34 progress: &crate::worker::Progress,
35) {
36 let phase = match progress.phase {
37 crate::worker::Phase::Download => crate::i18n::IDS_S6_DOWNLOADING,
38 crate::worker::Phase::Checking => crate::i18n::IDS_S6_CHECKING,
39 crate::worker::Phase::Uninstall => crate::i18n::IDS_S6_UNINSTALLING,
40 crate::worker::Phase::Backup => crate::i18n::IDS_S6_BACKUP,
41 crate::worker::Phase::Install => crate::i18n::IDS_S6_INSTALLING,
42 crate::worker::Phase::Configure => crate::i18n::IDS_S6_CONFIGURING,
43 };
44 crate::ui::set_text(dialog, crate::wizard::control_ids::IDC_S6_PHASE, phase);
45
46 let item = if progress.item.is_empty() {
47 String::new()
48 } else {
49 format!(
50 "{} — {}",
51 progress.item,
52 pacenotes_installer::size::human_progress(progress.item_done, progress.item_size)
53 )
54 };
55 crate::ui::set_text_raw(dialog, crate::wizard::control_ids::IDC_S6_ITEM, &item);
56
57 if let Some(position) = progress
58 .done
59 .saturating_mul(PROGRESS_SCALE as u64)
60 .checked_div(progress.total)
61 {
62 set_progress(dialog, position as u32);
63 }
64 if let Some(line) = &progress.log {
65 log_line(dialog, state, line);
66 }
67}
68
69pub unsafe fn on_cancel(dialog: HWND) -> isize {
73 let Some(state) = crate::wizard::page::state(dialog) else {
74 return crate::wizard::page::reply(dialog, 0);
75 };
76 if state.outcome.is_some() {
77 return crate::wizard::page::reply(dialog, 0);
78 }
79 let veto_close = 1;
80 if !crate::ui::confirm(
81 dialog,
82 &crate::i18n::load_string(crate::i18n::IDS_CANCEL_CONFIRM),
83 ) {
84 return crate::wizard::page::reply(dialog, veto_close);
85 }
86 state
87 .cancel
88 .store(true, std::sync::atomic::Ordering::Relaxed);
89 crate::ui::set_text(
90 dialog,
91 crate::wizard::control_ids::IDC_S6_PHASE,
92 crate::i18n::IDS_S6_CANCELLING,
93 );
94 log_line(dialog, state, "stopping at the user's request");
95 crate::wizard::page::reply(dialog, veto_close)
96}
97
98pub unsafe fn finish_page(dialog: HWND, phase: u16, next: Option<u16>) {
101 crate::ui::set_text(dialog, crate::wizard::control_ids::IDC_S6_PHASE, phase);
102 crate::ui::set_text_raw(dialog, crate::wizard::control_ids::IDC_S6_ITEM, "");
103 set_progress(dialog, PROGRESS_SCALE);
104 let sheet = crate::wizard::page::sheet(dialog);
105 crate::ui::enable(sheet, crate::ui::IDCANCEL, false);
106 crate::wizard::page::set_buttons(dialog, ctl::PSWIZB_NEXT);
107 match next {
108 None => wm::PostMessageW(sheet, ctl::PSM_PRESSBUTTON, ctl::PSBTN_NEXT as WPARAM, 0),
109 Some(page) => wm::PostMessageW(sheet, ctl::PSM_SETCURSELID, 0, page as LPARAM),
110 };
111}
112
113pub unsafe fn log_line(dialog: HWND, state: &mut crate::wizard::state::WizardState, text: &str) {
116 state.log.line(text);
117 crate::ui::append_line(dialog, crate::wizard::control_ids::IDC_S6_LOG, text);
118}
119
120pub unsafe fn show_log(dialog: HWND, state: &crate::wizard::state::WizardState) {
123 crate::ui::set_text_raw(
124 dialog,
125 crate::wizard::control_ids::IDC_S6_LOG,
126 &state.log.text(),
127 );
128 crate::ui::scroll_to_end(dialog, crate::wizard::control_ids::IDC_S6_LOG);
129}